﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web.UI;
using Ext.Net;

namespace KamLib.Controls
{
    public class RefStoreContainer : UserControl
    {

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            LoadStoreRegisters();
            CreateStores();
        }


        public class Pair
        {
            public int k { get; set; }
            public string n { get; set; }
            public Pair(int id, string name)
            {
                k = id;
                n = name;
            }
        }

        public class Pair3
        {
            public int k { get; set; }
            public string n { get; set; }
            public string desc { get; set; }
            public Pair3(int id, string name, string desc)
            {
                k = id;
                n = name;
                this.desc = desc;
            }
        }

        public List<Func<FieldInfo, bool>> StoreRegisters = new List<Func<FieldInfo, bool>>();



        public virtual void LoadStoreRegisters()
        {
            StoreRegisters.Add(f => f.FieldType == typeof(string[]) && InitStringsStore(f, NewStore(f)));
            StoreRegisters.Add(f => f.FieldType == typeof(string[][]) && InitStrings2Store(f, NewStore(f)));
            StoreRegisters.Add(f => f.FieldType == typeof(Pair[]) && InitPairStore(f, NewStore(f)));
            StoreRegisters.Add(f => f.FieldType == typeof(Pair3[]) && InitPair3Store(f, NewStore(f)));
            StoreRegisters.Add(f => f.FieldType == typeof(object[]) && InitObjectArrayStore(f, NewStore(f)));
        }

        public void CreateStores()
        {
            foreach (var pquery in GetType().GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField | BindingFlags.FlattenHierarchy))
            {
                foreach (var r in StoreRegisters)
                    if (r(pquery)) break;
            }
        }

        protected Store NewStore(FieldInfo pquery)
        {
            var store = new Store { ID = "ds" + pquery.Name.TrimStart('q') };
            Controls.Add(store);
            return store;
        }

        public bool InitQueryStore(Store store, string serviceUrl)
        {
            var reader = ((JsonReader)store.Reader.FirstOrDefault());
            if (reader == null)
            {
                store.Reader.Add(reader = new JsonReader
                {
                    IDProperty = "k",
                    Fields =
                    {
                        new RecordField { Name = "k" },
                        new RecordField { Name = "n" },
                    }
                });
                reader.Root = "d";
            }

            store.Proxy.Add(new HttpProxy
            {
                Url = serviceUrl,
                Json = true,
                Headers = { new Parameter { Name = "X-Ext.Net", Value = "delta=true" } },
            });
            store.BaseParams.AddValue("storeId", store.ID);

            return true;
        }

        public bool InitPairStore(FieldInfo pquery, Store store)
        {
            if (store.Reader.FirstOrDefault() == null)
            {
                store.Reader.Add(new JsonReader
                {
                    IDProperty = "k",
                    Fields =
                    {
                        new RecordField { Name = "k" },
                        new RecordField { Name = "n" },
                    }
                });
            }
            store.DataSource = pquery.GetValue(null);
            store.DataBind();

            return true;
        }

        public bool InitPair3Store(FieldInfo pquery, Store store)
        {
            if (store.Reader.FirstOrDefault() == null)
            {
                store.Reader.Add(new JsonReader
                {
                    IDProperty = "k",
                    Fields =
                    {
                        new RecordField { Name = "k" },
                        new RecordField { Name = "n" },
                        new RecordField { Name = "desc" },
                    }
                });
            }
            store.DataSource = pquery.GetValue(null);
            store.DataBind();

            return true;
        }

        public bool InitObjectArrayStore(FieldInfo pquery, Store store)
        {
            var src = (object[])pquery.GetValue(null);
            if (src == null || src.Length == 0) return false;

            if (store.Reader.FirstOrDefault() == null)
            {
                var reader = new JsonReader();
                store.Reader.Add(reader);
                foreach (var p in src[0].GetType().GetProperties())
                {
                    reader.Fields.Add(new RecordField(p.Name));
                }
            }

            store.DataSource = src;
            store.DataBind();

            return true;
        }

        public bool InitStringsStore(FieldInfo pquery, Store store)
        {
            var reader = ((ArrayReader)store.Reader.FirstOrDefault());
            if (reader == null)
            {
                store.Reader.Add(new ArrayReader
                {
                    IDProperty = "0",
                    Fields =
                    {
                        new RecordField { Name = "k", Mapping = "0" },
                        new RecordField { Name = "n", Mapping = "0" },
                    }
                });
            }
            store.DataSource = ((string[])pquery.GetValue(null)).Select(a => new[] { a });
            store.DataBind();

            return true;
        }

        public bool InitStrings2Store(FieldInfo pquery, Store store)
        {
            var reader = ((ArrayReader)store.Reader.FirstOrDefault());
            if (reader == null)
            {
                store.Reader.Add(new ArrayReader
                {
                    IDProperty = "0",
                    Fields =
                    {
                        new RecordField { Name = "k", Mapping = "0" },
                        new RecordField { Name = "n", Mapping = "1" },
                    }
                });
            }
            store.DataSource = pquery.GetValue(null);
            store.DataBind();

            return true;
        }

    }
}
